/*************************************************************************
	> File Name: Algorithm.h
	> Author: 
	> Mail: 
	> Created Time: 2021年12月22日 星期三 15时25分40秒
 ************************************************************************/

#include "WMarkAlgorithm.h"

namespace camera
{
    namespace algorithm
    {

        WMarkAlgorithm::WMarkAlgorithm()
        {
            ALOGI("%s ->", __func__);
            android::WatermarkManager *manager = android::WatermarkManager::getInstance();
            manager->setWaterMarkResultCallback(this);
            manager->startInput();
            ALOGI("%s <-", __func__);
        }

        WMarkAlgorithm::~WMarkAlgorithm()
        {
            ALOGI("%s ->", __func__);
            ALOGI("%s <-", __func__);
        }

        int WMarkAlgorithm::handle(algorithm_info_t info)
        {
            handleLog(info);
            handleStr(info);
            return 0;
        }

        int WMarkAlgorithm::handleStr(algorithm_info_t info)
        {
            unsigned char *bufptr = info.bufptr;
            int size = info.size;
            int rawWidth = info.rawWidth;
            int rawHeight = info.rawHeight;
            int channel = size / (rawWidth * rawHeight);
            string device_path_ = info.device_path_;

            bool on = isEnableWmark(device_path_, mAppStrCameraId, mEnableStr);
            if (!on) {
                return -1;
            }

            ALOGV("%s ->", __func__);
            if (!bufptr)
            {
                ALOGE("WMarkAlgorithm::%s error bufptr==NULL", __func__);
                return -1;
            }
            watermark_mtx.lock();
            int displayOffset = displayX + displayY * rawWidth;
            if (displayOffset >= (rawWidth * (rawHeight - watermark_h)))
            {
                displayOffset = 0;
            }
            for (int h = 0; h < watermark_h; h++)
            {
                for (int w = 0; w < watermark_w; w++)
                {
                    int index = h * rawWidth * channel + w * channel + displayOffset * channel;
                    unsigned char *b = &bufptr[ index + 0];
                    unsigned char *g = &bufptr[ index + 1];
                    unsigned char *r = &bufptr[ index + 2];
                    unsigned char *a = &bufptr[ index + 3];
                    if (image[h][w] != 0)
                    {
                        *b = 255;
                        *g = 255;
                        *r = 255;
                    } else {
                        if (mStrBgColor.enable) {
                            int _b = *b - mStrBgColor.b;
                            int _g = *g - mStrBgColor.g;
                            int _r = *r - mStrBgColor.r;
                            if (_b > 200 || _b < 0) {
                                _b = *b;
                            }

                            if (_g > 200 || _g < 0) {
                                _g = *g;
                            }

                            if (_r > 200 || _r < 0) {
                                _r = *r;
                            }
                            *b = (unsigned char)_b;
                            *g = (unsigned char)_g;
                            *r = (unsigned char)_r;
                        }
                    }
                }
            }
            watermark_mtx.unlock();
            ALOGV("%s <-", __func__);
            return 0;
        }

        int WMarkAlgorithm::handleLog(algorithm_info_t info)
        {
            unsigned char *bufptr = info.bufptr;
            int size = info.size;
            int rawWidth = info.rawWidth;
            int rawHeight = info.rawHeight;
            int channel = size / (rawWidth * rawHeight);
            string device_path_ = info.device_path_;

            bool on = isEnableWmark(device_path_, mAppLogoCameraId, mEnableImg);
            if (!on) {
                return -1;
            }

            ALOGV("%s ->", __func__);
            if (!bufptr)
            {
                ALOGE("WMarkAlgorithm::%s error bufptr==NULL", __func__);
                return -1;
            }
            watermarkLog_mtx.lock();
            int displayOffset = displayLogX + displayLogY * rawWidth;
            if (displayOffset >= (rawWidth * (rawHeight - watermarkLog_h)))
            {
                displayOffset = 0;
                
            }
            for (int h = 0; h < watermarkLog_h; h++)
            {
                for (int w = 0; w < watermarkLog_w; w++)
                {
                    uint8_t *tmp = &logImage[h * watermarkLog_w * log_channel + w * log_channel];
                    if (tmp[0] != 0)
                    {
                        int index = h * rawWidth * channel + w * channel + displayOffset * channel;
                        unsigned char *b = &bufptr[ index + 0];
                        unsigned char *g = &bufptr[ index + 1];
                        unsigned char *r = &bufptr[ index + 2];
                        unsigned char *a = &bufptr[ index + 3];

                        // *a = tmp[0];
                        *r = tmp[1];
                        *g = tmp[2];
                        *b = tmp[3];
                    }
                }
            }
            watermarkLog_mtx.unlock();
            ALOGV("%s <-", __func__);
            return 0;
        }

        void WMarkAlgorithm::onWaterMarkResult(WaterMarkImage wMarkImage)
        {
            ALOGV("v4l2-recv-watermark-result\n");
            if (!wMarkImage.image || wMarkImage.h > WM_IMAGE_H || wMarkImage.w > WM_IMAGE_W)
            {
                ALOGE("arg fail! no update send:watermark %dx%d      resv:watermark %dx%d     camera:\n",
                      wMarkImage.h, wMarkImage.w, WM_IMAGE_H, WM_IMAGE_W);
                return;
            }

            watermark_mtx.lock();
            mEnableStr = wMarkImage.enable;
            mAppStrCameraId = wMarkImage.id;
            displayX = wMarkImage.display_x;
            displayY = wMarkImage.display_y;
            watermark_w = wMarkImage.w;
            watermark_h = wMarkImage.h;
            mStrBgColor = wMarkImage.strBgColor;
            mMultiChannelDisplay = wMarkImage.multiChannel;
            memset((uint8_t *)image, 0, wMarkImage.h * wMarkImage.w);
            for (int h = 0; h < wMarkImage.h; h++)
            {
                for (int w = 0; w < wMarkImage.w; w++)
                {
                    image[h][w] = wMarkImage.image[h][w];
                }
            }
            watermark_mtx.unlock();
        }

        void WMarkAlgorithm::onWaterMarkLogResult(WaterMarkImage wMarkImage)
        {
            ALOGV("v4l2-recv-watermark-log-result\n");
            if (!wMarkImage.logImage || wMarkImage.h > WM_IMAGE_H || wMarkImage.w > WM_IMAGE_W)
            {
                ALOGE("arg fail! no update send:watermark %dx%d      resv:watermark %dx%d     camera:\n",
                      wMarkImage.h, wMarkImage.w, WM_IMAGE_H, WM_IMAGE_W);
                return;
            }

            watermarkLog_mtx.lock();
            mAppLogoCameraId = wMarkImage.id;
            mEnableImg = wMarkImage.enable;
            displayLogX = wMarkImage.display_x;
            displayLogY = wMarkImage.display_y;
            watermarkLog_w = wMarkImage.w;
            watermarkLog_h = wMarkImage.h;
            log_channel = wMarkImage.channel;
            memset((uint8_t *)logImage, 0, wMarkImage.h * wMarkImage.w * log_channel);
            memcpy(logImage, wMarkImage.logImage, wMarkImage.h * wMarkImage.w * log_channel);
            watermarkLog_mtx.unlock();
        }

        bool WMarkAlgorithm::isEnableWmark(string halCameraId, int appCameraId, int enbale) {
            int _halCameraId;
            int _appCameraId = appCameraId + 51 - 2;
            
            if (0 == enbale) {
                return false;
            }

            sscanf(halCameraId.c_str(), "/dev/video%d", &_halCameraId);
            ALOGV("halCameraId=%d _appCameraId=%d = 51 -2 + appCameraId(%d)", _halCameraId, _appCameraId, appCameraId);
            if (_appCameraId == _halCameraId || mMultiChannelDisplay) {
                return true;
            }
            return false;
        }
    } // algorithm
} // camera
